import dayjs from 'dayjs';
import { BrowserWindow } from 'electron';
import { convertStrCookieToDict, formatProxyInfo, parseProxyUrl } from '../../../../../utils';
import { PlatformUserAccountExpiredError } from '../../../errors.js';
import { sockProxyRules } from '../../../../../system/socksSessionProxy.js';

export const domUrl = 'https://creator.douyin.com/creator-micro/home';

export async function getHeaderTicketKey(params) {
  const {
    user_agent,
    localdata = [],
    timestamp = dayjs().unix(),
    cookies,
    third_id,
    proxy = '', 
    type = 'tuwen',
    signal
  } = params

  if(! third_id){
    throw new Error('third_id 不能为空');
  }

  if(! cookies){
    throw new Error('cookies 不能为空');
  }

  if(! localdata.length){
    throw new Error('localdata 不能为空');
  }

  let ticket = '';

  const item = localdata.find(item => item.key === 'security-sdk/s_sdk_sign_data_key/web_protect');

  if (item) {
    try {
      let localDataItem = JSON.parse(item.value);
      let webProtect = JSON.parse(localDataItem.data);
      ticket = webProtect.ticket;
    } catch (error) {
      console.error("JSON解析错误：", error);
    }
  }
  
  console.log(`third_id: ${third_id}`);
  console.log(`ticket: ${ticket}`);
  console.log(`timestamp: ${timestamp}`);

  const url = new URL(domUrl);

  let playwrightProxyFormat, httpxProxyFormat;

  if(proxy){
    const ipProxyInfo = parseProxyUrl(proxy);
    [playwrightProxyFormat, httpxProxyFormat] = formatProxyInfo(ipProxyInfo);
  }

  const cookieDict = convertStrCookieToDict(cookies);
  const cookieList = Object.keys(cookieDict).map(key => ({
    name: key,
    value: cookieDict[key],
    domain: url.host,
    path: "/",
    expires: dayjs().add(1, 'day').toDate().toUTCString()
  }));

  // 创建一个隐藏的浏览器窗口
  const win = new BrowserWindow({
    width: 1280,
    height: 800,
    show: false,
    webPreferences: {
      nodeIntegration: false,
      contextIsolation: true,
      javascript: true,
      images: false,
      styleSheets:false,
    }
  });

  let winDestroy = () => {
    win.destroy()
  }

  // 设置用户代理
  win.webContents.setUserAgent(user_agent);

  // 拦截 CSS 和图片请求
  win.webContents.session.webRequest.onBeforeRequest((details, callback) => {
    const url = details.url.toLowerCase();
    const blockExtensions = ['.css', '.png', '.jpg', '.jpeg', '.gif', '.webp'];
    
    const shouldBlock = blockExtensions.some(ext => url.endsWith(ext));
    callback({ cancel: shouldBlock });
  });

  // 设置代理
  if (httpxProxyFormat) {
    const { proxyRules, destroy: destroyProxyServer } = await sockProxyRules(`socks5://${httpxProxyFormat.auth.username}:${httpxProxyFormat.auth.password}@${httpxProxyFormat.host}:${httpxProxyFormat.port}`);
      
    let viewDestroy = winDestroy

    winDestroy = async () => {
      await destroyProxyServer()
      viewDestroy()
    }
    
    await win.webContents.session.setProxy({ proxyRules });
  }

  // 设置cookies
  for (const cookie of cookieList) {
    await win.webContents.session.cookies.set({
      url: domUrl,
      name: cookie.name,
      value: cookie.value,
      domain: cookie.domain,
      path: cookie.path,
      expirationDate: new Date(cookie.expires).getTime() / 1000,
      secure: true,
    })
  }

  // 监听中止信号
  signal?.addEventListener('abort', () => {
    winDestroy();
  });

  return new Promise((resolve, reject) => {
    // 注入本地存储数据
    win.webContents.on('dom-ready', () => {
      win.webContents.executeJavaScript(`
        for (const storage of ${JSON.stringify(localdata)}) {
          localStorage.setItem(storage.key, storage.value);
        }
      `);
    });

    win.webContents.on('did-finish-load', async () => {
      try {
        const currentUrl = win.webContents.getURL();

        if (currentUrl !== domUrl) {
          winDestroy();
          reject(new PlatformUserAccountExpiredError('登录信息已失效'));
          return;
        }

        const path = type == 'tuwen' ? '/web/api/media/aweme/create/' : '/web/api/media/aweme/create_v2/';

        const result = await win.webContents.executeJavaScript(`
          (async function(params) {
            const { third_id, ticket, timestamp, path } = params;

            while (! window.ZTSDK) {
              console.log('等待ZTSDK加载完成');
              await new Promise(resolve => setTimeout(resolve, 100));
            }
            
            const ZTSDK = window.ZTSDK;

            function Xn(t) {
              return !t || "string" == typeof t && -1 !== t.indexOf("pub.")
            }

            const e = third_id
            const kr = ["/web/api/media/aweme/create/", "/web/api/media/aweme/editor/compose/trigger/", "/passport/token/beat/web", "/web/api/media/aweme/delete/", "/web/api/media/aweme/reedit/", "/web/api/media/aweme/create_v2/", "/web/api/media/aweme/update_v2/"];
            const Cr = ZTSDK.SecureSDK

            Cr.setConfig({
                aid: 2906,
                scene: "web_protect",
                certType: "cookie",
                consumerPathList: kr,
                signVersion: 2
            });
            Cr.setConfig({
                aid: 2906,
                certType: "header",
                scene: "sso",
                namespace: "sso",
                consumerPathList: ["sso.douyin.com/check_login/"],
                providerPathList: ["sso.douyin.com/quick_login/v2/", "sso.douyin.com/check_qrconnect/"],
                urlRewriteRules: [["sso.douyin.com/check_login/", "/passport/sso/check_login/"]],
                signVersion: 2
            });
            Cr.setLoginStatus(!0);
            Cr.setUpdateDataWhenVerifySuccess(!0);
            Cr.setWebId(e);

            await Cr.start();
            const keysInfo = await ZTSDK.SecureSDK.cryptoSDK.getKeysInfoWithOrigin({ certType: 'cookie', scene: 'web_protect' });
            const keyRes = await ZTSDK.SecureSDK.cryptoSDK.signWithKeysInfo({
              sign_data: "ticket=${ticket}&path=${path}&timestamp=${timestamp}",
              req_content: "ticket,path,timestamp",
              timestamp: ${timestamp},
              certType: "cookie",
              scene: "web_protect",
              keysInfo: keysInfo,
              isNewCert: Xn(keysInfo.cert)
            });

            return {
              'bd-ticket-guard-version': 2,
              'bd-ticket-guard-web-version': 2,
              'bd-ticket-guard-iteration-version': 1,
              'bd-ticket-guard-web-sign-type': 1,
              'bd-ticket-guard-ree-public-key': keysInfo.b64PubKey,
              'bd-ticket-guard-client-data': keyRes.result
            };
          })({ third_id: '${third_id}', ticket: '${ticket}', timestamp: ${timestamp}, path: '${path}' })
        `);

        winDestroy();
        resolve(result);
      } catch (error) {
        winDestroy();
        reject(error);
      }
    });

    win.loadURL(domUrl).catch(error => {
      winDestroy();
      reject(error);
    });
  });
}